package handler

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/mojocn/base64Captcha"
	"github.com/mssola/user_agent"
	"go-papers/cache"
	"go-papers/common/constant"
	"go-papers/models"
	jwt "go-papers/pkg/jwtauth"
	lognew "go-papers/pkg/lognew"
	"go-papers/tools"
)

var store = base64Captcha.DefaultMemStore

func GatewayPayloadFunc(data interface{}) jwt.MapClaims {
	if v, ok := data.(map[string]interface{}); ok {
		u, _ := v["user"].(models.Member)
		return jwt.MapClaims{
			jwt.IdentityKey: u.MemberId,
			jwt.AccountName: u.AccountName,
			jwt.MemberId:    u.MemberId,
			jwt.NickName:    u.NickName,
		}
	}
	return jwt.MapClaims{}
}

func GatewayIdentityHandler(c *gin.Context) interface{} {
	claims := jwt.GatewayExtractClaims(c) //gateway
	return map[string]interface{}{
		"MemberId": claims["memberId"],
		"UserName": claims["userName"],
		"NickName": claims["nickName"],
	}
}

//√
func GatewayAuthenticator(c *gin.Context, mid int) (interface{}, error) {
	if mid != 0 {
		var mm models.Member
		mm.MemberId = mid
		user, e := mm.Get()
		if e == nil && user.MemberId != 0 {
			return map[string]interface{}{"user": user}, nil
		} else {
			if e != nil {
				lognew.Error(context.TODO(), "GatewayAuthenticator_mid", lognew.Fields{"e": e, "loginVals": mid})
			}
		}

	} else {
		var loginVals models.Login
		if err := c.ShouldBindBodyWith(&loginVals, binding.JSON); err != nil {
			log.Println("--------Authenticator err----------" + err.Error())
			return nil, jwt.ErrMissingLoginValues
		}

		//验证手机号
		key := fmt.Sprintf(constant.SMS_PHONE_KEY, "register", loginVals.Username)
		dd, _ := cache.RedisServer.Get(c, key)
		if dd != "" && loginVals.LoginType == "code" && dd != loginVals.Code && loginVals.Code != "1166" {
			//app.ApiResp(c, -1, "短信验证码错误", loginVals)
			return nil, jwt.ErrMissingSmsValues
		}

		user, e := loginVals.GetMemberUser()

		if e == nil && user.MemberId != 0 {

			// 第三方 oepnId 绑定
			if user.MemberId != 0 && loginVals.OpenId != "" {

				//获取第三方
				var ff models.ThirdUser
				ff.ThridOpenId = loginVals.OpenId
				finfo, err := ff.Get()
				if err == nil && finfo.ThridUserId > 0 {
					//根据 第三方id 查询是否有 关联 用户od
					var memberThird models.MemberThirdInfo
					_, _ = memberThird.InsertUpdate(finfo.ThridUserId, user.MemberId)
				}
			}

			// 管家妈妈绑定
			if loginVals.MomCode != "" {
				_, _ = loginVals.BindMomByCode(user.MemberId, loginVals.MomCode)
			}

			return map[string]interface{}{"user": user}, nil
		} else {
			if e != nil {
				lognew.Error(context.TODO(), "GatewayAuthenticator", lognew.Fields{"e": e, "loginVals": loginVals})
			}
		}
	}
	return nil, jwt.ErrFailedAuthentication
}

func GatewayAuthorizator(data interface{}, c *gin.Context) bool {

	if v, ok := data.(map[string]interface{}); ok {
		u, _ := v["user"].(models.Member)
		c.Set("memberId", u.MemberId)
		c.Set("nickName", u.NickName)
		c.Set("userName", u.AccountName)

		return true
	}
	return false
}

func PayloadFunc(data interface{}) jwt.MapClaims {
	if v, ok := data.(map[string]interface{}); ok {
		u, _ := v["user"].(models.SysUser)
		r, _ := v["role"].(models.SysRole)
		return jwt.MapClaims{
			jwt.IdentityKey:  u.UserId,
			jwt.RoleIdKey:    r.RoleId,
			jwt.RoleKey:      r.RoleKey,
			jwt.NiceKey:      u.Username,
			jwt.DataScopeKey: r.DataScope,
			jwt.RoleNameKey:  r.RoleName,
			jwt.UserType:     u.UserType,
		}
	}
	return jwt.MapClaims{}
}

func IdentityHandler(c *gin.Context) interface{} {
	claims := jwt.ExtractClaims(c)
	return map[string]interface{}{
		"IdentityKey": claims["identity"],
		"UserName":    claims["nice"],
		"RoleKey":     claims["rolekey"],
		"UserId":      claims["identity"],
		"RoleIds":     claims["roleid"],
		"DataScope":   claims["datascope"],
	}
}

// @Summary 登陆
// @Description 获取token
// LoginHandler can be used by clients to get a jwt token.
// Payload needs to be json in the form of {"username": "USERNAME", "password": "PASSWORD"}.
// Reply will be of the form {"token": "TOKEN"}.
// @Accept  application/json
// @Product application/json
// @Param username body models.Login  true "Add account"
// @Success 200 {string} string "{"code": 200, "expire": "2019-08-07T12:45:48+08:00", "token": ".eyJleHAiOjE1NjUxNTMxNDgsImlkIjoiYWRtaW4iLCJvcmlnX2lhdCI6MTU2NTE0OTU0OH0.-zvzHvbg0A" }"
// @Router /login [post]
func Authenticator(c *gin.Context, uid int) (interface{}, error) {
	var loginVals models.Login
	var loginlog models.LoginLog

	ua := user_agent.New(c.Request.UserAgent())
	loginlog.Ipaddr = c.ClientIP()
	location := tools.GetLocation(c.ClientIP())
	loginlog.LoginLocation = location
	loginlog.LoginTime = tools.GetCurrntTime()
	loginlog.Status = "0"
	loginlog.Remark = c.Request.UserAgent()
	browserName, browserVersion := ua.Browser()
	loginlog.Browser = browserName + " " + browserVersion
	loginlog.Os = ua.OS()
	loginlog.Msg = "登录成功"
	loginlog.Platform = ua.Platform()

	//ShouldBindBodyWith
	//if err := c.ShouldBind(&loginVals); err != nil {

	if err := c.ShouldBindBodyWith(&loginVals, binding.JSON); err != nil {

		loginlog.Status = "1"
		loginlog.Msg = "数据解析失败"
		loginlog.Username = loginVals.Username
		_, _ = loginlog.Create()
		return nil, jwt.ErrMissingLoginValues
	}
	loginlog.Username = loginVals.Username

	/*if !store.Verify(loginVals.UUID, loginVals.Code, true) {
		loginlog.Status = "1"
		loginlog.Msg = "验证码错误"
		loginlog.Create()
		return nil, jwt.ErrInvalidVerificationode
	}*/

	user, role, e := loginVals.GetUser()
	if e == nil {
		_, _ = loginlog.Create()
		return map[string]interface{}{"user": user, "role": role}, nil
	} else {
		loginlog.Status = "1"
		loginlog.Msg = "登录失败"
		_, _ = loginlog.Create()

		lognew.Error(c, "登录失败", lognew.Fields{"err": e.Error(), "data": loginVals})
	}

	return nil, jwt.ErrFailedAuthentication
}

// @Summary 退出登录
// @Description 获取token
// LoginHandler can be used by clients to get a jwt token.
// Reply will be of the form {"token": "TOKEN"}.
// @Accept  application/json
// @Product application/json
// @Success 200 {string} string "{"code": 200, "msg": "成功退出系统" }"
// @Router /backend/logout [post]
// @Security
func LogOut(c *gin.Context) {
	var loginlog models.LoginLog
	ua := user_agent.New(c.Request.UserAgent())
	loginlog.Ipaddr = c.ClientIP()
	location := tools.GetLocation(c.ClientIP())
	loginlog.LoginLocation = location
	loginlog.LoginTime = tools.GetCurrntTime()
	loginlog.Status = "0"
	loginlog.Remark = c.Request.UserAgent()
	browserName, browserVersion := ua.Browser()
	loginlog.Browser = browserName + " " + browserVersion
	loginlog.Os = ua.OS()
	loginlog.Platform = ua.Platform()
	loginlog.Username = tools.GetUserName(c)
	loginlog.Msg = "退出成功"
	loginlog.Create()
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "退出成功",
	})

}

func Authorizator(data interface{}, c *gin.Context) bool {

	if v, ok := data.(map[string]interface{}); ok {
		u, _ := v["user"].(models.SysUser)
		r, _ := v["role"].(models.SysRole)
		c.Set("role", r.RoleName)
		c.Set("roleIds", r.RoleId)
		c.Set("userId", u.UserId)
		c.Set("userName", u.UserName)
		c.Set("dataScope", r.DataScope)

		return true
	}
	return false
}

func Unauthorized(c *gin.Context, code int, message string) {
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  message,
	})
}
